#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#define F_CPU 80000000
#include <util/delay.h>



#define SEG_a 0x01
#define SEG_b 0x02
#define SEG_c 0x04
#define SEG_d 0x08
#define SEG_e 0x10
#define SEG_f 0x20
#define SEG_g 0x40
#define SEG_dot 0x80

uint16_t EEMEM Edigit=800;
uint16_t Def_digit=300;

//global variables for isr()
uint16_t digit, decimal, digit_addressed=0;
uint8_t d[8];
uint8_t pulsing=0;
uint16_t pulseinterval;
uint16_t maxpulseinterval=512;
uint16_t ProgrammedDigit=0;
uint8_t LedOn=0;

//keys definition
#define GO		7
#define RIGHT 	6
#define LEFT 	5
#define KPIN  PINB
uint8_t keypressed=1;		//a key was pressed
uint8_t t1=0;
uint8_t Powersave=0;

//character definition
unsigned char seg[]=
{
	//negative logic
	(SEG_g),							 			// 0
	(SEG_a|SEG_d|SEG_e|SEG_f|SEG_g),				// 1
	(SEG_c|SEG_f),					 				// 2
	(SEG_e|SEG_f), 									// 3
	(SEG_a|SEG_d|SEG_e), 							// 4
	(SEG_b|SEG_e),					 				// 5
	(SEG_b), 										// 6
	(SEG_d|SEG_e|SEG_f|SEG_g),						// 7
	(SEG_dot), 										// 8
	(SEG_e), 										// 9
	(SEG_a|SEG_b|SEG_c|SEG_d|SEG_e|SEG_f|SEG_g) 	// NULL DISPLAY FOR POWER SAVE
};


//interrupt routine for character display
ISR(TIMER0_OVF_vect)
{
	pulseinterval++;
	if (pulseinterval>maxpulseinterval) pulseinterval=0;
	if ((pulsing==1) && (pulseinterval < maxpulseinterval/2))
	{
		PORTB=(1<<DDB0) | (1<<DDB1)| (1<<DDB2)| (1<<DDB3);
	}
	else
	{	
		PORTD = ~(d[digit_addressed]);

		switch (digit_addressed)
		{
			case 0: {PORTB=(0<<DDB0) | (1<<DDB1)| (1<<DDB2)| (1<<DDB3); PORTA=PORTA&~_BV(1);} 	//clear bit 1 port a
			break;
			case 1: {PORTB=(1<<DDB0) | (0<<DDB1)| (1<<DDB2)| (1<<DDB3); PORTA|=_BV(1);} 		//set   bit 1 port a
			break;
			case 2: {PORTB=(1<<DDB0) | (1<<DDB1)| (0<<DDB2)| (1<<DDB3); PORTA=PORTA&~_BV(1);}	//clear bit 1 port a
			break;
			default:{PORTB=(1<<DDB0) | (1<<DDB1)| (1<<DDB2)| (0<<DDB3); PORTA=PORTA&~_BV(1);}	//clear bit 1 port a
		}
		if (LedOn==1) PORTB |= (1<<DDB4);
		digit_addressed++;
		if(digit_addressed>=4) digit_addressed=0;
	}
}



void display(void)
{
	uint8_t min, sec;
	if (Powersave!=1)
	{
		min=digit/60;
		sec=digit-min*60;

		//computing digits
		d[4]=min/10;
		d[5]=min-d[4]*10;
		d[6]=sec/10;
		d[7]=sec-d[6]*10;

		d[0]= seg[d[4]];
		d[1]= seg[d[5]];
		d[2]= seg[d[6]];
		d[3]= seg[d[7]];
	}
	else
	{
		d[0]= seg[10];
		d[1]= seg[10];
		d[2]= seg[10];
		d[3]= seg[10];
	}
}

void init(void)
{
	TCNT0 = 0x00 ;
	TCCR0B = 0x03; //prescaler of 64
	TIMSK = 0x02; //overflow irq req'd
	sei();

	DDRA =3;
	PORTA=_BV(0)|_BV(1)|_BV(2);	//all 3 bits of PORT A are set -> DP lit, beep on
	PORTB|=_BV(0)|_BV(1)|_BV(2)|_BV(3)|_BV(4);
	DDRB |=_BV(0)|_BV(1)|_BV(2)|_BV(3);

	PORTD=0xff;
	DDRD =0xff;
	pulsing=1;				//pulsing
	pulseinterval=0;
	digit= eeprom_read_word(&Edigit);
	if (digit==0xFFFF)		//not programmed EEPROM
	{
		digit=Def_digit;
		eeprom_write_word(&Edigit, Def_digit);
	}

					//set default value 
	display();				//starting value
	ProgrammedDigit=digit;	//if there is no delay programming, that one is the default value of 240s


}


void beep(void)
{
//	PORTA=7;
	PORTA|=_BV(0);			//enable beep
	_delay_ms(10);
//	PORTA=6;
	PORTA=PORTA& ~_BV(0);	//disable beep
	_delay_ms(30);

}

void readkeys(void)
{
	uint16_t i,j;
//LEFT AND RIGHT keys

//LEFT key
	if (bit_is_clear(KPIN, LEFT) && bit_is_clear(KPIN, RIGHT))
	{
		eeprom_write_word(&Edigit, digit);
	}
	else
	if bit_is_clear(KPIN, LEFT) 
	{
		keypressed=1;
		digit--;
		if (digit==0xFFFF) digit=0;
		ProgrammedDigit=digit;
	}
	else
//RIGHT key
	if bit_is_clear(KPIN, RIGHT) 
	{
		keypressed=1;
		digit++;
		if (digit>5999) digit=5999;
		ProgrammedDigit=digit;
	}
	else
		if bit_is_clear(KPIN, GO) 
	{
		keypressed=1;
		Powersave=0;
//		PORTA=7;
		PORTA=_BV(0)|_BV(1)|_BV(2);
		_delay_ms(10);
//		PORTA=6;
		PORTA=_BV(1)|_BV(2);
		_delay_ms(30);
		LedOn=1;
		pulsing=0;
		ProgrammedDigit=digit;
		for (i=0;i<ProgrammedDigit;i++)
		{
			_delay_ms(100);
			digit--;
			display();
		}
		digit=ProgrammedDigit;
		display();
		pulsing=1;
		LedOn=0;
		for(j=0; j<10; j++)
		{
			beep();
		}
		pulsing=1;
	}
	else	keypressed=0;



}

void testfordisplaysleep(void)
{
	if (keypressed==0)	//if there is no key pressed
	{
		t1++;			
		if (t1==170)	//wait ~10 seconds
		{
			t1=0;		
			beep();		//beep every ~10 seconds while sleeping
			Powersave=1;//and put display to sleep
		}
	}
	else				//on any key press 
	{	
		t1=0;			
		Powersave=0;	//wake up display
	}
}

int main()
 
{
	init();
	_delay_ms(10);
	LedOn=0;
	PORTA=_BV(1)|_BV(2);	//turn off beep, keep DP lit
	t1=0;
	keypressed=1;
	while(1)
	{
		readkeys();			//read key
		display();			//display number
		_delay_ms(6);		//wait a little bit
		testfordisplaysleep();
	}

}
 
